package com.jsgt.greekfire.common.http

import android.text.TextUtils
import com.fhx.core.AppContext
import com.fhx.core.utils.NetworkUtil
import com.fhx.core.utils.SharePreferencesUtil
import com.fhx.core.utils.SystemUtil
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.jsgt.greekfire.*
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
//import tech.linjiang.pandora.Pandora
import java.net.Proxy
import java.util.concurrent.TimeUnit
import kotlin.math.abs


/**
 * author fhx
 * create time 2020/4/24 20:39
 **/
object RetrofitManager {
    private val urlArrayList = ArrayList<String>()
    private var urlIndex = 0//正在用哪个域名

    private var mRetrofit: Retrofit? = null
    private var oKEXRetrofit: Retrofit? = null
    private var blockRetrofit: Retrofit? = null
    private var serverRetrofit: Retrofit? = null
    var blockUrl = "http://192.168.0.146:8082/" //区块浏览器地址
    var serverUrl = "http://192.168.0.146:9996/atr-wallet/" //服务器地址

    init {
        when (ENV_TYPE) {
            //开发环境
            ENV_DEV -> {
                urlArrayList.add("http://192.168.0.142:9991/wallet/")
                blockUrl = "http://192.168.0.146:8082/"
                serverUrl = "http://192.168.0.146:9996/atr-wallet/"
                //urlArrayList.add("http://192.168.0.113:8881/wallet/")
                //urlArrayList.add("http://192.168.0.113:8681/wallet/")
//                urlArrayList.add("http://192.168.0.146:8081/greekfire/")
            }
            //测试环境
            ENV_TEST -> {
                urlArrayList.add("http://192.168.0.146:8681/wallet/")
                blockUrl = "http://192.168.0.146:8082/"
                serverUrl = "http://192.168.0.146:9996/atr-wallet/"
//              urlArrayList.add("http://api.greekfire.top:8081/greekfire/")
//                urlArrayList.add("http://47.108.171.224:8081/greekfire/")
            }
            //正式环境
            ENV_PRO -> {
//                urlArrayList.add("http://47.103.106.138:8881/wallet/")
                urlArrayList.add("http://47.108.136.230:9991/wallet/")
                blockUrl = "http://47.108.136.214:8081/"
                serverUrl = "http://47.108.29.25:9996/atr-wallet/"
//                urlArrayList.add("http://47.101.67.204:8681/wallet/")
//                urlArrayList.add("http://apiv5.utios.me:18081/greekfire/")
//                urlArrayList.add("http://apiv4.utios.me:18081/greekfire/")
//                urlArrayList.add("http://apiv3.utios.me:18081/greekfire/")//apiv3经常被DDos攻击，放到最后面
            }
        }
    }

    @Synchronized
    private fun <T> createService(serviceClass: Class<T>): T {
        val urlSize = urlArrayList.size
        if (mRetrofit == null) {
            mRetrofit = Retrofit.Builder()
                .baseUrl(urlArrayList[urlIndex % urlSize])
                .addConverterFactory(GsonConverterFactory.create(gson))
                .client(genericOkClient())
                .build()
        }
        return mRetrofit!!.create(serviceClass)
    }

    private var okexService: OKEXService? = null

    @Synchronized
    fun createOKEXService(): OKEXService {
        if (okexService == null) {
            if (oKEXRetrofit == null) {
                val url = "http://47.241.133.65:50051/"
                oKEXRetrofit = Retrofit.Builder()
                    .baseUrl(url)
                    .addConverterFactory(GsonConverterFactory.create(gson))
                    .client(genericOkClient())
                    .build()
            }
            okexService = oKEXRetrofit!!.create(OKEXService::class.java)
        }
        return okexService!!
    }

    private var serverService: ServerService? = null

    @Synchronized
    fun createServerService(): ServerService {
        if (serverService == null) {
            if (serverRetrofit == null) {
                serverRetrofit = Retrofit.Builder()
                    .baseUrl(serverUrl)
                    .addConverterFactory(GsonConverterFactory.create(gson))
                    .client(genericOkClient())
                    .build()
            }
            serverService = serverRetrofit!!.create(ServerService::class.java)
        }
        return serverService!!
    }


    private var blockService: BlockService? = null

    @Synchronized
    fun createBlockService(): BlockService {
        if (blockService == null) {
            if (blockRetrofit == null) {
                blockRetrofit = Retrofit.Builder()
                    .baseUrl(blockUrl)
                    .addConverterFactory(GsonConverterFactory.create(gson))
                    .client(genericOkClient())
                    .build()
            }
            blockService = blockRetrofit!!.create(BlockService::class.java)
        }
        return blockService!!
    }

    var switchTime = 0L

    @Synchronized
    fun switchBaseUrl(failedUrl: String?) {
        if (!NetworkUtil.isNetworkAvailable() || ENV_TYPE != ENV_PRO || urlArrayList.size < 2) {
            //没有网络就不切换了
            return
        }
        var change = false//是否应该切域名
        if (mRetrofit == null) {
            //这个mRetrofit等于空，说明还没发起新的请求，此时不用继续切
            //LogUtils.debug("这个mRetrofit等于空，说明还没发起新的请求，此时不用继续切")
        } else {
            if (TextUtils.isEmpty(failedUrl)) {
                change = true
            } else {
                val urlSize = urlArrayList.size
                val curUrl = urlArrayList[urlIndex % urlSize]
                //LogUtils.debug("failedUrl:${failedUrl},curUrl:${curUrl}")
                if (failedUrl!!.startsWith(curUrl)) {
                    //LogUtils.debug("当前域名有问题切换")
                    change = true
                } else {
                    //不是当前域名
                    //LogUtils.debug("不是当前域名")
                }
            }
        }
        if (change) {
            val curTime = System.currentTimeMillis()
            if (abs(curTime - switchTime) > 2000) {
                switchTime = curTime
                urlIndex++
                _userInterface = null
                _walletInterface = null
                _coinInterface = null
                mRetrofit = null
                //LogUtils.debug("切换网络域名:${urlIndex}")
            } else {
                //间隔时间太短，基本上就是同一批网络请求失败的,不需要频繁切换
            }
        }
    }

    fun processNetException(e: Throwable, url: String?) {
        switchBaseUrl(url)//出异常就切域名
        /*if(e != null) {
            if (e is java.net.SocketTimeoutException) {
                switchBaseUrl(url)
            } else {
                if (e.message != null && e.message!!.startsWith("Failed to connect to $url")) {
                    switchBaseUrl(url)
                }
            }
        }*/
    }

    private var _userInterface: UserService? = null
    private var _walletInterface: WalletService? = null
    private var _coinInterface: CoinService? = null
    private var marketInterface: MarketService? = null
    private var coinCurrencyInterface: CoinCurrencyService? = null
    private var otcTraddingInterface: OTCTraddingService? = null
    private var tradingInterface: TradingService? = null
    private var privilegeInterface: PrivilegeService? = null
    private var entrustInterface: EntrustService? = null


    val entrustService: EntrustService
        get() {
            if (entrustInterface == null) {
                entrustInterface = createService(EntrustService::class.java)
            }
            return entrustInterface!!
        }

    val userService: UserService
        get() {
            if (_userInterface == null) {
                _userInterface = createService(UserService::class.java)
            }
            return _userInterface!!
        }
    val walletService: WalletService
        get() {
            if (_walletInterface == null) {
                _walletInterface = createService(WalletService::class.java)
            }
            return _walletInterface!!
        }
    val coinService: CoinService
        get() {
            if (_coinInterface == null) {
                _coinInterface = createService(CoinService::class.java)
            }
            return _coinInterface!!
        }

    val marketService: MarketService
        get() {
            if (marketInterface == null) {
                marketInterface = createService(MarketService::class.java)
            }
            return marketInterface!!
        }
    val coinCurrencyService: CoinCurrencyService
        get() {
            if (coinCurrencyInterface == null) {
                coinCurrencyInterface = createService(CoinCurrencyService::class.java)
            }
            return coinCurrencyInterface!!
        }
    val otcTraddingService: OTCTraddingService
        get() {
            if (otcTraddingInterface == null) {
                otcTraddingInterface = createService(OTCTraddingService::class.java)
            }
            return otcTraddingInterface!!
        }

    val tradingService: TradingService
        get() {
            if (tradingInterface == null) {
                tradingInterface = createService(TradingService::class.java)
            }
            return tradingInterface!!
        }

    val privilegeService: PrivilegeService
        get() {
            if (privilegeInterface == null) {
                privilegeInterface = createService(PrivilegeService::class.java)
            }
            return privilegeInterface!!
        }

    private val gson: Gson by lazy {
        GsonBuilder()
            .registerTypeAdapter(Int::class.java, IntegerDefault0Adapter())
            .registerTypeAdapter(Double::class.java, DoubleDefault0Adapter())
            .registerTypeAdapter(Long::class.java, LongDefault0Adapter())
            .registerTypeAdapter(Boolean::class.java, BooleanDefaultAdapter())
            .registerTypeAdapter(Float::class.java, FloatDefault0Adapter())
            .create()
    }

    private fun genericOkClient(): OkHttpClient {
//        val httpLoggingInterceptor = HttpLoggingInterceptor(
//            object : HttpLoggingInterceptor.Logger {
//                override fun log(message: String) {
//                    LogUtils.verbose("$message")
        // 如果是 json 格式内容则打印 json
//                    if ((message.startsWith("{") && message.endsWith("}")) ||
//                        (message.startsWith("[") && message.endsWith("]"))
//                    )
//                        LogUtils.json(message)
//                    else
//                        LogUtils.verbose(message)
//                }
//            })

//        httpLoggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
        val httpLoggingInterceptor = HttpLoggingInterceptor("http")
        httpLoggingInterceptor.setPrintLevel(HttpLoggingInterceptor.Level.BODY)
        return OkHttpClient.Builder()
            .connectTimeout(5_000L, TimeUnit.MILLISECONDS)
            .readTimeout(10_000L, TimeUnit.MILLISECONDS)
            .writeTimeout(10_000L, TimeUnit.MILLISECONDS)
            .addNetworkInterceptor(httpLoggingInterceptor)
            .proxy(Proxy.NO_PROXY)
//            .addInterceptor(Pandora.get().interceptor)
            .addInterceptor(object : Interceptor {
                override fun intercept(chain: Interceptor.Chain): Response {
                    val token = SharePreferencesUtil.getString(
                        AppContext.instance,
                        TOKEN_VALUE, ""
                    )
                    val request: Request = chain.request()
                        .newBuilder()
                        .addHeader("Content-Type", "application/json")
                        .addHeader("device", SystemUtil.getDeviceUUID(AppContext.instance))
                        .addHeader("platform", "Android")
                        .addHeader("token", token)
                        .addHeader("Cookie", App.context.getString(R.string.okex_language))
                        .build()
                    return chain.proceed(request)
                }
            }
            )
            .build()
    }

}